home *** CD-ROM | disk | FTP | other *** search
- /*
- * DTSSampleCSAM.c
- * Copyright © 1992-93 Apple Computer Inc. All Rights Reserved.
- *
- * This is a simple CSAM (Catalog Service Access Module)
- * for AOCE. It is based on the example written by OCE
- * engineering. This sample calls the Personal Directory
- * routines to do it's work. Since it doesn't use the
- * Authentication interface, only "guest" access is provided.
- *
- * The functions in this file are called by the driver
- * "glue" file that is linked at the start of the DRVR
- * code segment. Note that the driver glue used here is
- * not identical with either MPW ('DRVW' resource) or
- * THINK (Device Driver Project option). As noted in
- * the introduction to the driver glue file, this driver
- * must be linked as a pure code segment.
- *
- * DTS Sample CSAM is based on sample code written by
- * Steve Fisher, Eric Trehus, and Mike Cleron of Apple
- * OCE engineering.
- */
-
- #include "DTSSampleCSAM.h"
- #ifdef THINK_C
- #include <ASM.h>
- #pragma parameter __D0 __MyGetA4()
- long __MyGetA4(void) = 0x200C; /* move.l a4, d0 */
- #endif
- #define USER_STATUS (pb->ioResult)
- #define DCTL (*devCtlEnt) /* Driver control record */
-
-
- /*
- * Note: OpenDRVR must be called synchronously as it
- * allocates memory.
- */
- OSErr
- OpenDRVR(
- register CntrlParam *pb,
- register DCtlPtr devCtlEnt
- )
- {
- register DTSSampleCSAMInfoPtr infoPtr;
- StringHandle dsamName;
- RString dsamRStringName;
- short i;
- #define PB (INFO.dirParamBlock)
- #define INST (PB.instantiateDSAMPB)
-
- if (pb->ioCompletion != NULL)
- USER_STATUS = openErr; /* Synchronous only */
- else {
- USER_STATUS = noErr;
- infoPtr = (DTSSampleCSAMInfoPtr) DCTL.dCtlStorage;
- if (infoPtr == NULL) {
- /*
- * First call: initialize our private data area.
- */
- infoPtr = (DTSSampleCSAMInfoPtr) NewPtrSysClear(
- sizeof (DTSSampleCSAMInfo)
- );
- USER_STATUS = MemError();
- if (USER_STATUS == noErr && infoPtr == NULL)
- USER_STATUS = memFullErr; /* Can't happen */
- if (USER_STATUS == noErr) {
- DCTL.dCtlStorage = (Handle) infoPtr;
- #ifdef THINK_C
- INFO.originalA4 = __MyGetA4();
- #endif
- }
- #if DEBUG_LOG
- if (USER_STATUS == noErr) {
- INFO.auditPtr = InitAudit(kCSAMCreatorID, 64, TRUE, FALSE);
- LogText('DRVR', "\pDTSSampleCSAM Start");
- }
- #endif
- for (i = 0; USER_STATUS == noErr && i < kNumIcons; i++)
- USER_STATUS = GetCSAMIcon(infoPtr, i);
- LogStatus('DRVR', USER_STATUS, "\pGetCSAMIcon");
- if (USER_STATUS == noErr) {
- /*
- * We have a control block and the icons, now
- * instantiate the CSAM
- */
- dsamName = GetString(kCSAMName);
- if (dsamName == NULL)
- USER_STATUS = resNotFound;
- else {
- HLock((Handle) dsamName);
- USER_STATUS = MemError();
- }
- LogStatus('DRVR', USER_STATUS, "\pGetString(kCSAMName)");
- }
- if (USER_STATUS == noErr) {
- /*
- * Setup the parameter block. Note that
- * NewPtrSysClear initialized all fields
- * to zero. DirInstantiateDSAM requires the
- * dsRefNum to be zero.
- */
- OCEPToRString(
- *dsamName,
- smRoman,
- &dsamRStringName,
- kRStringMaxBytes
- );
- ReleaseResource((Handle) dsamName);
- }
- if (USER_STATUS == noErr) {
- /*
- * We're almost there. All we need to do now is to
- * tell the CSAM Manager our name and the names of
- * the functions to call when something happens in
- * our little world.
- *
- * This sample CSAM does not use Authentication
- * procedure callbacks.
- */
- INST.dsamName = &dsamRStringName;
- INST.dsamKind = kCSAMCreatorID;
- INST.dsamData = (Ptr) infoPtr;
- INST.dsamDirProc = (ProcPtr) CSAM_DSProc;
- INST.dsamDirParseProc = (ProcPtr) CSAM_DSParseProc;
- INST.dsamAuthProc = NULL;
- USER_STATUS = DirInstantiateDSAM(&PB);
- LogStatus('DRVR', USER_STATUS, "\pDirInstantiateDSAM");
- }
- }
- }
- return (USER_STATUS);
- #undef PB
- #undef INST
- }
-
- /*
- * This sample CSAM does not use Prime calls. They may be
- * needed for CSAM's that need periodic time.
- */
- OSErr
- PrimeDRVR(
- register CntrlParam *pb,
- register DCtlPtr devCtlEnt
- )
- {
- #pragma unused (devCtlEnt)
- USER_STATUS = paramErr;
- LogStatusX('DRVR', USER_STATUS, "\pPrimeDRVR");
- return (paramErr);
- }
-
-
- /*
- * This sample CSAM does not use Control calls. They might
- * be needed in order to support the KillIO call.
- */
- OSErr
- ControlDRVR(
- register CntrlParam *pb,
- register DCtlPtr devCtlEnt
- )
- {
- #pragma unused (devCtlEnt)
- USER_STATUS = controlErr;
- LogStatusX('DRVR', USER_STATUS, "\pControlDRVR");
- return (controlErr);
- }
-
-
- /*
- * This sample CSAM does not use Status calls.
- */
- OSErr
- StatusDRVR(
- register CntrlParam *pb,
- register DCtlPtr devCtlEnt
- )
- {
- #pragma unused (devCtlEnt)
- USER_STATUS = statusErr;
- LogStatusX('DRVR', USER_STATUS, "\pStatusDRVR");
- return (statusErr);
- }
-
- /*
- * Close deletes all storage allocated by OpenDRVR.
- * Note that Close uses Memory Manager calls and,
- * hence, must not be called at interrupt time
- * or from an I/O completion routine.
- */
- OSErr
- CloseDRVR(
- register CntrlParam *pb,
- register DCtlPtr devCtlEnt
- )
- {
- register DTSSampleCSAMInfoPtr infoPtr;
- CatalogInfoPtr catalogInfoPtr;
- short i;
- Handle iconHandle;
-
- LogTextX('CLOS', "\pCalling Close Driver");
- USER_STATUS = noErr;
- infoPtr = (DTSSampleCSAMInfoPtr) DCTL.dCtlStorage;
- if (infoPtr != NULL) {
- /*
- * Go through the private storage carefully to
- * delete all information that was allocated by
- * our routines. Note that the order of operation
- * was carefully chosen to make sure we make exactly
- * one attempt to delete an item of information,
- * even if some process fails because of an error.
- *
- * First, dump the storage used by our directory icons.
- */
- for (i = 0; USER_STATUS == noErr && i < kNumIcons; i++) {
- iconHandle = INFO.icons[i].iconData;
- if (iconHandle != NULL) {
- INFO.icons[i].iconData = NULL;
- DisposHandle(iconHandle);
- USER_STATUS = MemError();
- LogError('CLOS', USER_STATUS);
- }
- }
- /*
- * Now, dump any directories that we have hanging around.
- */
- while (USER_STATUS == noErr) {
- /*
- * Get the next directory record. Exit if there
- * are no more. Else, close the associated
- * I/O process.
- */
- catalogInfoPtr = (CatalogInfoPtr)
- DequeueFirst(&INFO.catalogQHdr);
- if (catalogInfoPtr == NULL)
- break;
- LogRString('CLOS', &catalogInfoPtr->directoryName);
- USER_STATUS = ADASClosePAB(catalogInfoPtr->refNum);
- LogStatus('CLOS', USER_STATUS, "\pADASClosePAB");
- /*
- * Dispose of the directory record *before* checking
- * for a status error from ADASClosePAB()
- */
- DisposPtr((Ptr) catalogInfoPtr);
- if (USER_STATUS == noErr) {
- USER_STATUS = MemError();
- LogStatus('CLOS', USER_STATUS, "\pDisposPtr(catalogInfoPtr)");
- }
- }
- if (USER_STATUS == noErr) {
- /*
- * So far, so good. Make sure the queue header is
- * clean and dump the info pointer. Note that the
- * driver control pointer in DCTL.dCtlStorage still
- * contains infoPtr.
- */
- INFO.catalogQHdr.qHead = NULL;
- INFO.catalogQHdr.qTail = NULL;
- DisposPtr((Ptr) infoPtr);
- USER_STATUS = MemError();
- }
- /*
- * If (and only if) we were able to dispose of the
- * entire private storage area, we can finally clear
- * the driver private storage pointer.
- */
- if (USER_STATUS == noErr)
- DCTL.dCtlStorage = NULL;
- }
- LogTextX('CLOS', "\pClose Exits");
- return (USER_STATUS);
- }
-
- /*
- * DequeueFirst is a wrapper for the system Dequeue
- * function that returns the first element from the
- * queue, or NULL if the queue is empty. Note that
- * an empty queue is not an error.
- */
- QElemPtr
- DequeueFirst(
- register QHdrPtr theQueue
- )
- {
- register QElemPtr result;
-
- result = theQueue->qHead;
- if (result != NULL) {
- /*
- * Dequeue can fail if the first element in
- * the queue was removed by an interrupt
- * service routine. This is not an error.
- * By working in this manner, we do not need
- * to block interrupts (except when actually
- * modifying the queue). In particular, the
- * frequent case of querying an empty queue
- * does not lock out interrupts.
- */
- if (Dequeue(result, theQueue) != noErr)
- result = NULL;
- }
- return (result);
- }
-
-